package com.xysoft.framework.web;

import java.io.IOException;
import java.util.Map;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;

public class AssetFilter extends AbstractFilter {

	public static final String DEFAULT_ASSET_PREFIX = "/asset/";

	private String assetPrefix = DEFAULT_ASSET_PREFIX;
	private Map<String, String> mimeMap;

	public void setAssetPrefix(String assetPrefix) {
		this.assetPrefix = assetPrefix;
	}

	public void setMimeMap(Map<String, String> mimeMap) {
		this.mimeMap = mimeMap;
	}

	@Override
	protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
			throws ServletException, IOException {
		if (StringUtils.startsWithIgnoreCase(request.getServletPath(), assetPrefix)) {
			Resource location = new ClassPathResource(StringUtils.removeStartIgnoreCase(request.getServletPath(), assetPrefix));
			if (!location.exists()) {
				response.sendError(HttpServletResponse.SC_NOT_FOUND);
				return;
			}
			long contentLength = location.contentLength();
			long lastModified = location.lastModified();

			long ifModifiedSince = 0;
			try {
				ifModifiedSince = request.getDateHeader("If-Modified-Since");
			} catch (IllegalArgumentException ex) {
				ifModifiedSince = -1;
			}

			if (ifModifiedSince > 0) {
				if (ifModifiedSince >= lastModified) {
					response.sendError(HttpServletResponse.SC_NOT_MODIFIED, "");
					return;
				}
			}

			response.setDateHeader("Last-Modified", lastModified);
			response.setDateHeader("Expires", lastModified + (1000 * 60 * 60 * 24 * 360 * 10));

			if (mimeMap != null && mimeMap.containsKey(FilenameUtils.getExtension(location.getFilename()))) {
				response.setContentType(mimeMap.get(FilenameUtils.getExtension(location.getFilename())));
			}
			response.setContentLength(Long.valueOf(contentLength).intValue());
			response.getOutputStream().write(IOUtils.toByteArray(location.getInputStream()));

		} else {
			chain.doFilter(request, response);
		}
	}

}
